<template>
  <div>
    <div class="container">
      <div class="client-state-container">
        <div class="state-container">
          <span>连接状态:</span>
          <span>{{readyState == true ? '已连接':'未连接'}}</span>
        </div>
      </div>

      <div class="chat-container">
        <div class="chat-container-top"
             ref="chatMessage">
          <!-- 用户列表 -->
          <vue-drag-resize class="chat-left-container"
                           :w="200"
                           :h="450">
            <div class="chat-left-container-outside">
              <div class="chat-left-container-inner">
                <span>当前在线</span>
                <ul>
                  <li v-for="(list,index) in online_user_list"
                      :key="index"><i class="el-icon-s-custom"
                       style="font-size:20px"></i>&nbsp;&nbsp;{{JSON.parse(list.user).cname}}</li>
                </ul>
              </div>
              <!-- <div class="chat-left-container-inner-right">
                <i class="el-icon-right"
                  style="font-size:35px;color:#fff"></i>
              </div> -->
            </div>

          </vue-drag-resize>
          <div class="chat-container-top-message-out">
            <div class="chat-container-top-message"
                 v-for="(value,index) in message_list"
                 :key='index'>
              <div class="message-time-container">
                <span>{{value.time}}</span>
              </div>
              <div :class="value.send_user.username == user.username?'right-container chat-container-text-name' : 'left-container chat-container-text-name'">
                {{value.send_user.cname}}</div>
              <div :class="value.send_user.username==user.username?'right-container right-border-r chat-container-text-message':'left-container left-border-r chat-container-text-message'">
                <div v-show="value.message_type=='chat'">{{value.message}}</div>
                <el-image v-show="value.message_type=='expression'"
                          style="width:100px;height:100px"
                          :src="value.message">
                </el-image>
                <el-image v-show="value.message_type=='base64'"
                          style="width:100px;height:100px;"
                          :src="value.message"
                          :preview-src-list="
                          srcList">
                </el-image>
              </div>
            </div>
          </div>
        </div>

        <el-progress :percentage="percentage"
                     :format="format"
                     :stroke-width="3"
                     color="rgba(172, 23, 185, 0.6)">
        </el-progress>

        <div class="tools-container">
          <div class="tools-container-inner">
            <div class="tools"
                 @click="clickImg">
              <input type="file"
                     style="display:none"
                     ref="imgsInputs"
                     id="imgsInputs"
                     @change="fileUpload($event)">
              <i class="el-icon-picture"
                 style="font-size:35px"></i>
            </div>
            <div class="tools">
              <i class="el-icon-folder-opened"
                 style="font-size:35px"></i>
            </div>
          </div>
        </div>

        <div class="chat-container-bottom">
          <el-input type="textarea"
                    :rows="2"
                    placeholder="请输入消息内容"
                    v-model="message"> </el-input>
          <div class="icon-container">
            <img src="../assets/icon_icon.png"
                 alt=""
                 style="width:100%;height:100%"
                 @click="showExpression()">
          </div>
          <el-button type="success"
                     @click="sendMessage">发送</el-button>
        </div>

      </div>
    </div>
    <el-dialog :visible.sync="dialogVisible"
               width="50%"
               :showClose="false">
      <!-- tree start -->
      <div class="expression-icon-container">
        <div class="expression-icon-container-img expression-img"
             v-for="(val,index) in expression_icon_list"
             :key="index">

          <el-image style="width: 100%; height: 100%;border-radius: 5px;"
                    :src="val.url"
                    :fit="fit"
                    @click="checkExpression(val.url)"></el-image>
        </div>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import md5 from 'js-md5'
let base64 = require('js-base64').Base64;
import VueDragResize from 'vue-drag-resize';
export default {
  components: {
    VueDragResize
  },
  created () {
    this.getStorage();
    // this.checkWebSocket();
  },
  beforeDestroy () {
    clearTimeout(this.timer_timeout);
    this.timer_timeout = null;
  },
  data () {
    return {
      message: '',
      user: [],
      ws: [],
      message_list: [],
      dialogVisible: false,
      fit: 'fit',
      percentage: 0,
      srcList: [],//聊天图片
      progress: false,
      readyState: true,// websocket 连接状态
      timer_timeout: null,
      online_user_list: [],
      win: [],// 弹窗对象
      expression_icon_list: [
        { 'url': require("../assets/icon/chat_icon_1.jpg") },
        { 'url': require("../assets/icon/chat_icon_2.jpg") },
        { 'url': require("../assets/icon/chat_icon_3.jpg") },
        { 'url': require("../assets/icon/chat_icon_4.jpg") },
        { 'url': require("../assets/icon/chat_icon_5.jpg") },
        { 'url': require("../assets/icon/chat_icon_6.jpg") },
        { 'url': require("../assets/icon/chat_icon_7.jpg") },
        { 'url': require("../assets/icon/chat_icon_8.jpg") },
        { 'url': require("../assets/icon/chat_icon_9.jpg") },
        { 'url': require("../assets/icon/chat_icon_10.jpg") },
        { 'url': require("../assets/icon/chat_icon_11.jpg") },
        { 'url': require("../assets/icon/chat_icon_12.jpg") },
        { 'url': require("../assets/icon/chat_icon_13.jpg") },
        { 'url': require("../assets/icon/chat_icon_14.jpg") },
        { 'url': require("../assets/icon/chat_icon_15.jpg") },
        { 'url': require("../assets/icon/chat_icon_16.jpg") },
        { 'url': require("../assets/icon/chat_icon_17.jpg") },
        { 'url': require("../assets/icon/chat_icon_18.jpg") },
        { 'url': require("../assets/icon/chat_icon_19.jpg") },
        { 'url': require("../assets/icon/chat_icon_20.jpg") },
        { 'url': require("../assets/icon/chat_icon_21.jpg") },
        { 'url': require("../assets/icon/chat_icon_22.jpg") },
        { 'url': require("../assets/icon/chat_icon_23.jpg") },
        { 'url': require("../assets/icon/chat_icon_24.jpg") },
        { 'url': require("../assets/icon/chat_icon_25.jpg") },
        { 'url': require("../assets/icon/chat_icon_26.jpg") },
        { 'url': require("../assets/icon/chat_icon_27.jpg") }
      ]
    }
  },
  methods: {
    open () {
      this.$prompt('请给自己取一个响亮又大气的名字(必须是中文！！)', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        showCancelButton: false,
        showClose: false,
        closeOnClickModal: false,
        closeOnPressEscape: false,
        inputPattern: /^[\u4e00-\u9fa5]{2,4}$/,
        inputErrorMessage: '名字格式不正确'
      }).then(({ value }) => {
        let num = Math.ceil(Math.random() * 10000);
        let username = md5(`${value}${num}`);
        let cname = value;
        this.user = { 'username': username, 'cname': cname };
        window.localStorage.setItem('__USER__', base64.encode(JSON.stringify(this.user)));
        this.openWebsocket();
      })
    },
    //建立websocket链接
    openWebsocket () {
      if ("WebSocket" in window) {
        // 打开一个 web socket
        this.ws = new WebSocket("ws://47.104.128.87:9998");
        // 检测是否可以成功连接服务器
        if (this.timer_timeout) {
          clearTimeout(this.timer_timeout);
          this.timer_timeout = null;
        }
        this.timer_timeout = setTimeout(() => {
          if (this.ws.readyState == 0) {
            this.readyState = false;
            this.checkWebSocket();
          }
        }, 500)
        // 检查服务器连接状态
        this.ws.onopen = () => {
          // Web Socket 已连接上，使用 send() 方法发送数据
          /** 
           * 初次链接握手 绑定uid
          */
          let userInit = JSON.stringify({ 'type': 'init', 'username': this.user.username, 'cname': this.user.cname });
          this.ws.send(userInit);
          this.readyState = true;
          // this.$notify({
          //   type: 'success',
          //   message: '连接服务器成功！',
          //   position: 'bottom-right',
          //   showClose: false
          // })
        };
        // 检测服务器是否与客户端断开连接
        this.ws.onmessage = (e) => {
          // console.log(e.data);
          clearTimeout(this.timer_timeout);
          this.timer_timeout = null;
          //console.log(this.timer_timeout);
          this.clientOnLine();
          let data = e.data;
          let message = JSON.parse(data);
          // console.log(message);
          let messageStr = "";
          switch (message.type) {
            case 'message':
              if (this.percentage == 10) {
                this.percentage = 60;
              }
              this.message_list.push(message);
              if (this.percentage == 60) {
                this.percentage = 80;
              }
              this.goBottom();
              if (this.percentage == 80) {
                this.percentage = 100;
              }
              clearTimeout(this.timer_timeout);
              this.timer_timeout = null;
              this.timer_timeout = setTimeout(() => {
                this.percentage = 0;
              }, 2000);
              if (message.message_type == 'base64') {
                this.srcList.push(message.message);
              }
              break;
            case 'init':
              if (this.user.username == message.username) {
                messageStr = '“' + this.user.cname + '”进入聊天室';
              } else {
                messageStr = '“' + message.cname + '”上线了！';
              }
              this.$notify({
                title: '提醒',
                message: ('i', { style: 'color: teal' }, messageStr),
                position: 'bottom-right',
                showClose: false
              });
              break;
            case 'user_group':
              // console.log(Object.values(message['user_group']));
              if (Object.values(message['user_group'])) {
                this.online_user_list = Object.values(message['user_group']);
              }
              break;
          }
        };

        this.ws.onclose = () => {
          // 关闭 websocket
          // alert("连接已关闭...");
          this.ws.onopen = () => {
            this.ws.send(`关闭`);
          }
        };
      } else {
        this.$message({
          type: 'error',
          message: '您的浏览器不支持我们的对话基础！您可以更换Google Chrome'
        });
      }


    },
    async getStorage () {
      const userInfo = await window.localStorage.getItem('__USER__');
      if (!userInfo) {
        this.open();
      } else {
        this.user = JSON.parse(base64.decode(userInfo));
        this.openWebsocket();
      }
    },
    sendMessage () {
      if (!this.message) {
        this.$message({
          type: 'error',
          message: '这是一条空消息！！'
        })
        return false;
      }
      let message = JSON.stringify({ 'type': 'message', 'send_user': this.user, 'message': this.message, 'message_type': 'chat' });
      // 进度条
      clearInterval(this.timer_timeout);
      if (this.percentage == 0) {
        this.percentage = 10;
      }
      this.ws.send(message);
      this.message = '';
    },
    // 滚动到最底部
    goBottom () {
      this.$nextTick(function () {
        let el = document.getElementsByClassName('chat-container-top-message-out')[0];
        el.scrollTop = el.scrollHeight; // 滚动高度
      })
    },
    // 展示聊天表情
    showExpression () {
      this.dialogVisible = true;
    },
    //选择表情发送
    checkExpression (url) {
      let message = JSON.stringify({ 'type': 'message', 'send_user': this.user, 'message': url, 'message_type': 'expression' });
      this.ws.send(message);
      this.dialogVisible = false;
    },
    // 进度条
    format () {
      return this.percentage == 100 ? '发送成功' : this.percentage == 0 ? '' : '发送中...';
    },
    checkWebSocket () {
      //当链接状态为0的时候服务器断开连接 执行弹窗提示服务器断开连接
      if (this.timer_timeout) {
        clearTimeout(this.timer_timeout);
      }
      if (this.ws.readyState == 0) {
        this.$message({
          type: 'error',
          message: '连接服务器失败！！',
          duration: 2000
        })
        this.timer_timeout = setTimeout(() => {
          this.openWebsocket();
        }, 3000)
        return;
      }
    },
    clientOnLine () {
      //console.log('client Online');
      let time = 30000;// 30s的时间没有数据往来判定为短线 执行重新连接
      if (this.timer_timeout) {
        clearTimeout(this.timer_timeout);
        this.timer_timeout = null;
      }
      this.timer_timeout = setTimeout(() => {
        this.readyState = false;
        if (this.readyState == false) {
          this.openWebsocket();
        }
      }, time);
    },
    // 点击图片发送按钮
    clickImg () {
      document.getElementById('imgsInputs').click();
      //   this.refs.imgsInputs.el.click();
    },
    //图片生成base64字符串
    image2Base64 (img) {
      var canvas = document.createElement("canvas");
      //console.log(canvas);
      canvas.width = img.width;
      canvas.height = img.height;
      var ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0, img.width, img.height);
      var dataURL = canvas.toDataURL("image/png");
      return dataURL;
    },
    //上传照片或者文件方法
    fileUpload (event) {
      // let _this = this;
      let files = event.target.files;
      let image = new Image();
      image.src = window.URL.createObjectURL(files.item(0));
      image.onload = () => {
        // 默认按比例压缩
        let w = image.width,
          h = image.height;
        let scale = w / h;
        w = 300;
        h = w / scale;
        // 默认图片质量为0.7，quality值越小，所绘制出的图像越模糊
        let quality = 1.0;
        //生成canvas
        let canvas = document.createElement('canvas');
        let ctx = canvas.getContext('2d');
        // 创建属性节点
        let anw = document.createAttribute("width");
        anw.nodeValue = w;
        let anh = document.createAttribute("height");
        anh.nodeValue = h;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.drawImage(image, 0, 0, w, h);
        let ext = image.src.substring(image.src.lastIndexOf(".") + 1).toLowerCase();//图片格式
        let base64_str = canvas.toDataURL("image/" + ext, quality);
        this.ws.send(JSON.stringify({ "message": base64_str, 'send_user': this.user, "message_type": 'base64', 'type': 'message' }));
      }
    },
    // base 64 转二进制流
    //   Base64ToFile (base64) {
    //     var arr = base64.split(','), mime = arr[0].match(/:(.*?);/)[1],

    //       bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);

    //     while (n--) {

    //       u8arr[n] = bstr.charCodeAt(n);

    //     }
    //     let blob_str = new Blob([u8arr], { type: mime });
    //     // let data = JSON.stringify({ type: 'blob', message: blob_str });
    //     // this.ws.onopen = () => {
    //     this.ws.send({ message: blob_str, "type": 'blob' });
    //     //console.log(blob_str);

  }
}
</script>
<style lang="less">
@import url("../../public/css/chat.css");
</style>